package br.academia.controller;

import java.util.ArrayList;
import java.util.Collection;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import br.academia.arq.dao.ExercicioTreinoDAO;
import br.academia.arq.dao.TreinoDAO;
import br.academia.arq.erros.DAOException;
import br.academia.arq.erros.NegocioException;
import br.academia.dominio.Aluno;
import br.academia.dominio.Exercicio;
import br.academia.dominio.ExercicioTreino;
import br.academia.dominio.Funcionario;
import br.academia.dominio.Treino;
import br.academia.negocio.AbstractProcessador;
import br.academia.negocio.ExercicioTreinoProcessador;
import br.academia.negocio.TreinoProcessador;
import br.academia.util.Formatador;
import br.academia.util.Validador;

@SuppressWarnings("serial")
@Component("treino")
@Scope("session")
public class TreinoController extends AbstractController{
	/** JSPs chamadas pelo Controller */
	public static final String CADASTRAR_JSP = "/admin/treino/cadastrar_treino.jsf";
	public static final String ALTERAR_JSP = "/admin/treino/alterar_treino.jsf";
	public static final String LISTAR_JSP = "/admin/treino/listar_treino.jsf";
	public static final String MENU_JSP = "/admin/treino/menu_treino.jsf";
	
	/** Objeto usado nos fluxos do Controller */
	private Treino treino;
	
	/** Objetos usados nos fluxos do Controller */
	private Exercicio exercicio;
	private ExercicioTreino exercicioTreino;
	private Integer repeticoes;
	private Integer numeroTreinos;
	
	/** Atributos usados nas listagens do Controller */
	private String nome;
	private String descricao;
	private String dataInicio;
	private String dataFim;
	private Aluno aluno;
	private Funcionario funcionario;
	
	private Collection<ExercicioTreino> listaExercicios;
	
	/** Lista populada pelos fluxos */
	private Collection<Treino> listaTreinos;
	
	/**
	 * Construtor público
	 */
	public TreinoController(){
		reset();
	}
	
	/**
	 * Método usado para reiniciar os atributos do Controller
	 */
	public void reset(){
		treino = new Treino();
		funcionario = new Funcionario();
		exercicio = new Exercicio();
		exercicioTreino = new ExercicioTreino();
		aluno = new Aluno();
		listaTreinos = new ArrayList<Treino>();
		listaExercicios = new ArrayList<ExercicioTreino>();
		repeticoes = null;
		numeroTreinos = null;
		nome = "";
		descricao = "";
		dataInicio = "";
		dataFim = "";
	}
	
	/**
	 * Método utilizado para entrar no menu de Estado
	 * @return
	 */
	public String entrarMenu(){
		reset();
		
		return forward(MENU_JSP);
	}
	
	/**
	 * Método utilizado para entrar na listagem de Estado
	 * @return
	 */
	public String entrarListagem(){
		reset();
		
		return listar();
	}
	
	/**
	 * Método que popula a lista de Estados e redireciona para a listagem
	 * @return
	 */
	public String listar(){
		TreinoDAO dao = null;
		
		try {
			dao = getDAO(TreinoDAO.class); 
			
			if(Validador.isEmpty(nome) && Validador.isEmpty(descricao) && Validador.isEmpty(dataInicio) && Validador.isEmpty(dataFim) && Validador.isEmpty(aluno) && Validador.isEmpty(funcionario)){
				listaTreinos = dao.findAll(Treino.class);
			}else{
				setValores();
				
				listaTreinos = dao.findTreinoLike(treino);
			}
		} catch (DAOException e) {
			addMensagem("Ocorreu um erro na listagem de Treinos. Por favor, contate a administração do sistema.");
			e.printStackTrace();
			return reload();
		}finally{
			if(dao != null){
				dao.close();
			}
		}
		
		if(hasMensagens()){
			return reload();
		}
		
		if(listaTreinos.isEmpty()){
			addMensagem("Não foi encontrada nenhum Treino para a busca realizada.");
		}
		
		return forward(LISTAR_JSP);
	}
	
	/**
	 * Método utilizado para entrar na página de alteração de Estados
	 * @return
	 */
	public String entrarAlteracao(){
		reset();
		TreinoDAO dao = null;
		ExercicioTreinoDAO exercicioDao = null;
		
		Integer id = Integer.valueOf(getParameter("id"));
		
		if(id == null || id <= 0){
			addMensagem("Ocorreu um erro na alteração do Treino selecionada. Por favor, contate a administração do sistema.");
			return reload();
		}
		
		try {
			dao = getDAO(TreinoDAO.class);
			exercicioDao = getDAO(ExercicioTreinoDAO.class);

			treino = dao.findByPrimaryKey(id, Treino.class);
			
			listaExercicios = exercicioDao.findExerciciosByTreino(treino);
			
			nome = treino.getNome();
			descricao = treino.getDescricao();
			dataInicio = treino.getDataInicioFormatada();
			dataFim = treino.getDataFimFormatada();
			aluno = treino.getAluno();
			funcionario = treino.getFuncionario();
		} catch (DAOException e) {
			e.printStackTrace();
		}finally{
			close(dao);
		}
		return forward(ALTERAR_JSP);
	}
	
	/**
	 * Método que realiza a chamada à classe de negócio que realiza
	 * a atualização do Estado na base de dados.
	 * @return
	 */
	public String alterar(){
		addMensagem(Validador.validaPreenchimento("Nome", nome));
		addMensagem(Validador.validaPreenchimento("Aluno", aluno));
		addMensagem(Validador.validaPreenchimento("Funcionario", funcionario));
		addMensagem(Validador.validaPreenchimento("Data de Início", dataInicio));
		addMensagem(Validador.validaPreenchimento("Data de Fim", dataFim));
		
		if(hasMensagens()){
			return reload();
		}
		
		setValores();
		
		TreinoProcessador processador = new TreinoProcessador();
		
		try {
			processador.execute(AbstractProcessador.ALTERAR, treino);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
			return reload();
		}
		
		return entrarListagem();
	}
	

	
	/**
	 * Método que realiza a chamada à classe de negócio que realiza
	 * a atualização da ExercicioTreino na base de dados.
	 * @return
	 */
	public String adicionarExercicio(){
		addMensagem(Validador.validaPreenchimento("Exercicio", exercicio));
		addMensagem(Validador.validaPreenchimento("Séries", numeroTreinos));
		addMensagem(Validador.validaPreenchimento("Repetições", repeticoes));
		
		if(hasMensagens()){
			return reload();
		}
		
		setValores();
		
		ExercicioTreinoProcessador processador = new ExercicioTreinoProcessador();
		
		try {
			processador.execute(AbstractProcessador.CADASTRAR, exercicioTreino);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
			return reload();
		}
		
		return entrarAlteracao();
	}
	
	/**
	 * Método que realiza a chamada à classe de negócio que realiza
	 * a atualização da ExercicioTreino na base de dados.
	 * @return
	 */
	public String removerExercicio(){
		if(hasMensagens()){
			return reload();
		}
		
		setValores();

		Integer id = Integer.valueOf(getParameter("exercicioTreinoId"));
		exercicioTreino.setId(id);
		
		id = Integer.valueOf(getParameter("exercicioId"));
		exercicioTreino.getExercicio().setId(id);
		
		ExercicioTreinoProcessador processador = new ExercicioTreinoProcessador();
		
		try {
			processador.execute(AbstractProcessador.REMOVER, exercicioTreino);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
			return reload();
		}
		
		return entrarAlteracao();
	}
	
	/**
	 * Método utilizado para entrar na página de cadastro de Ideais
	 * @return
	 */
	public String entrarCadastro(){
		reset();
		
		return forward(CADASTRAR_JSP);
	}
	
	/**
	 * Método que realiza a chamada à classe de negócio que realiza
	 * a inserção do Estado na base de dados.
	 * @return
	 */
	public String cadastrar(){
		addMensagem(Validador.validaPreenchimento("Nome", nome));
		addMensagem(Validador.validaPreenchimento("Aluno", aluno));
		addMensagem(Validador.validaPreenchimento("Funcionario", funcionario));
		addMensagem(Validador.validaPreenchimento("Data de Início", dataInicio));
		addMensagem(Validador.validaPreenchimento("Data de Fim", dataFim));
		
		if(hasMensagens()){
			return reload();
		}
		
		setValores();
		
		TreinoProcessador processador = new TreinoProcessador();
		
		try {
			processador.execute(AbstractProcessador.CADASTRAR, treino);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
		}
		
		return entrarListagem();
	}
	
	/**
	 * Método utilizado na página de listagem de Estados, para remover
	 * um Estado selecionado.
	 * @return
	 */
	public String remover(){
		Integer id = Integer.valueOf(getParameter("id"));
		
		if(id == null || id <= 0){
			addMensagem("Ocorreu um erro na remoção do item selecionado. Por favor, contate a administração do sistema.");
			return reload();
		}
		
		
		TreinoDAO dao = null;
		
		try {
			dao = getDAO(TreinoDAO.class);

			treino = dao.findByPrimaryKey(id, Treino.class);
			
			nome = treino.getNome();
			descricao = treino.getDescricao();
			dataInicio = treino.getDataInicioFormatada();
			dataFim = treino.getDataFimFormatada();
		} catch (DAOException e) {
			e.printStackTrace();
		}finally{
			close(dao);
		}
		
		TreinoProcessador processador = new TreinoProcessador();
		
		try {
			processador.execute(AbstractProcessador.REMOVER, treino);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
		}
		
		return entrarListagem();
	}
	
	/**
	 * Método utilizado para cancelar a operação em curso
	 * @return
	 */
	public String cancelar(){
		return entrarMenu();
	}
	
	public Treino getTreino() {
		return treino;
	}

	private void setValores(){
		treino.setNome(nome.trim());
		treino.setDataInicio(Formatador.getInstance().parseDate(dataInicio));
		treino.setDataFim(Formatador.getInstance().parseDate(dataFim));
		treino.setAluno(aluno);
		treino.setFuncionario(funcionario);
		treino.setDescricao(descricao);
		
		exercicioTreino.setExercicio(exercicio);
		exercicioTreino.setNumeroTreinos(numeroTreinos);
		exercicioTreino.setRepeticoes(repeticoes);
		exercicioTreino.setTreino(treino);
	}

	public Collection<Treino> getListaTreinos() {
		return listaTreinos;
	}

	public void setListaTreinos(Collection<Treino> listaTreinos) {
		this.listaTreinos = listaTreinos;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getNome() {
		return nome;
	}

	public Exercicio getExercicio() {
		return exercicio;
	}

	public void setExercicio(Exercicio exercicio) {
		this.exercicio = exercicio;
	}

	public Integer getRepeticoes() {
		return repeticoes;
	}

	public void setRepeticoes(Integer repeticoes) {
		this.repeticoes = repeticoes;
	}

	public String getDescricao() {
		return descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	public String getDataInicio() {
		return dataInicio;
	}

	public void setDataInicio(String dataInicio) {
		this.dataInicio = dataInicio;
	}

	public String getDataFim() {
		return dataFim;
	}

	public void setDataFim(String dataFim) {
		this.dataFim = dataFim;
	}

	public Collection<ExercicioTreino> getListaExercicios() {
		return listaExercicios;
	}

	public void setListaExercicios(Collection<ExercicioTreino> listaExercicios) {
		this.listaExercicios = listaExercicios;
	}

	public void setTreino(Treino treino) {
		this.treino = treino;
	}

	public Aluno getAluno() {
		return aluno;
	}

	public void setAluno(Aluno aluno) {
		this.aluno = aluno;
	}

	public Integer getNumeroTreinos() {
		return numeroTreinos;
	}

	public void setNumeroTreinos(Integer numeroTreinos) {
		this.numeroTreinos = numeroTreinos;
	}

	public ExercicioTreino getExercicioTreino() {
		return exercicioTreino;
	}

	public void setExercicioTreino(ExercicioTreino exercicioTreino) {
		this.exercicioTreino = exercicioTreino;
	}

	public Funcionario getFuncionario() {
		return funcionario;
	}

	public void setFuncionario(Funcionario funcionario) {
		this.funcionario = funcionario;
	}
}
